package com.hyjy.music

import android.app.Application
import android.database.ContentObserver
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.text.TextUtils
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.hyjy.music.bean.MusicBean
import com.hyjy.music.util.MUSIC_WHITE_LIST
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.util.*

class MusicViewModel(val app: Application) : AndroidViewModel(app) {
    companion object {
        val URI_MUSIC: Uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    }

    /**
     * 音乐播放列表
     */
    var musicBeanList = MutableLiveData<MutableList<MusicBean>>()

    /**
     * 获取音乐列表
     */
    fun getMusicList(): MutableList<MusicBean> = musicBeanList.value ?: mutableListOf()

    /**
     * 当前正在播放的音乐
     */
    var currentMusicBean = MutableLiveData<MusicBean?>()

    private var contentObserver: ContentObserver? = null

    /**
     * 查询音乐列表
     */
    fun queryMusicList(onCompletion: (() -> Unit)? = null) {
        viewModelScope.launch(Dispatchers.IO) {
            val list = getMusicData()
            withContext(Dispatchers.Main) {
                musicBeanList.value = list
                onCompletion?.invoke()
            }
        }
    }

    fun updateCurrentMusicBean(musicBean: MusicBean?) {
        currentMusicBean.value = musicBean
    }

    fun registerMusicChangeCallback(onMusicChange: Boolean.() -> Unit) {
        contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
            override fun onChange(selfChange: Boolean) {
                super.onChange(selfChange)
                onMusicChange.invoke(selfChange)
            }
        }.apply {
            app.contentResolver.registerContentObserver(URI_MUSIC, true, this)
        }
    }

    fun unregisterMusicChangeCallback() {
        contentObserver?.run {
            app.contentResolver.unregisterContentObserver(this)
        }
    }

    /**
     * 查找播放的位置
     *
     * @return 播放的位置
     */
    fun getMusicPlayingPosition(): Int {
        currentMusicBean.value?.let {
            getMusicList().forEachIndexed { index, bean ->
                if (it == bean) {
                    return index
                }
            }
        }
        return -1
    }

    /**
     * 获取音乐列表
     */
    private fun getMusicData(): MutableList<MusicBean> {
        val contentResolver = app.contentResolver ?: return mutableListOf()
        // 获取所有歌曲
        val list = mutableListOf<MusicBean>()
        val cursor = contentResolver.query(
            URI_MUSIC,
            null,
            null,
            null,
            MediaStore.Audio.Media.DEFAULT_SORT_ORDER
        ) ?: return list
        while (cursor.moveToNext()) {
            val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
            if (!isSuitableMusic(url)) {
                // 根据音乐文件扩展名,判断是否支持播放
                continue
            }
            val duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
            if (duration < 60 * 1000) {
                // 过滤时长小于60秒的
                continue
            }
            val musicBean = MusicBean(
                name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)),
                title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)),
                singer = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)),
                album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)),
                url = url,
                size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)),
                duration = duration,
                id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID)),
                albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)),
                embedPic = getEmbeddedPicture(url)
            )
            if ("<unknown>" == musicBean.singer) {
                musicBean.singer = "未知歌手"
            }
            list.add(musicBean)
        }
        cursor.close()
        list.sort()
        return list
    }

    private fun getEmbeddedPicture(url: String?): ByteArray? {
        return kotlin.runCatching {
            // 能够获取多媒体文件元数据的类
            val mediaMetadataRetriever = MediaMetadataRetriever()
            mediaMetadataRetriever.setDataSource(url) // 设置数据源
            mediaMetadataRetriever.embeddedPicture.apply {
                mediaMetadataRetriever.release()
            }
        }.getOrNull()
    }

    private fun isSuitableMusic(url: String): Boolean {
        val file = File(url)
        if (!file.exists()) {
            return false
        }
        if (file.length() <= 0) {
            return false
        }
        val name = file.name
        for (suffix in MUSIC_WHITE_LIST) {
            if (name.endsWith(suffix)) {
                return true
            }
        }
        if (name.contains(".")) {
            val lastIndex = name.lastIndexOf(".")
            val suffix = name.substring(lastIndex + 1)
            if (TextUtils.equals(suffix.lowercase(Locale.getDefault()), "kwm")) {
                // 酷我音乐格式,不支持播放
                return false
            }
            if (TextUtils.equals(suffix.lowercase(Locale.getDefault()), "?")) {
                // 其他不支持播放的格式,后续增加
                return false
            }
        }
        return false
    }
}